﻿//Copyright 2014 Thomas Rega

//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at

//http://www.apache.org/licenses/LICENSE-2.0

//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace TinyDeduplicator
{
    public partial class MainWindow : Window
    {
        static Thread thread;

        private void runScan()
        {
            if ((object)thread != null && thread.IsAlive)
            {
                thread.Interrupt();

                if (!thread.Join(50))
                {
                    thread.Abort();
                }

                btnScan.Content = "Scan";
                Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, new Action(() => lblStatus.Content = "Scan stopped..."));
            }
            else
            {
                string path = txtLocation.Text;

                if (Directory.Exists(path))
                {
                    dataGrid.EnableRowVirtualization = options.selectionStrategy == SelectionStrategy.None;

                    dataGrid.ItemsSource = new List<DisplayFile>();
                    DirectoryInfo root = new DirectoryInfo(txtLocation.Text);

                    thread = new Thread(() => runDeduplicate(root));
                    thread.Start();

                    btnScan.Content = "Stop";
                }
                else
                {
                    System.Windows.MessageBox.Show("Unable to locate the directory: " + path, "Unable to locate directory");
                }
            }
        }

        private void runDeduplicate(DirectoryInfo dir)
        {
            try
            {
                ICollection<DisplayFile> rows = new List<DisplayFile>();

                using (RecursiveDeduplicator deduplicator = new RecursiveDeduplicator(Dispatcher, lblStatus))
                {
                    deduplicator.deduplicate(dir);

                    IList<DeduplicationFile> files = deduplicator.getDuplicates();

                    for (int i = 0; i < files.Count; ++i )
                    {
                        DeduplicationFile file = files[i];
                        FileInfo fileInfo = file.fileInfo;
                        bool selected = false;

                        if (options.selectionStrategy == SelectionStrategy.KeepFirst)
                        {
                            if(i != 0 && file.Equals(files[i - 1]))
                            {
                                selected = true;
                            }
                        }
                        else if (options.selectionStrategy == SelectionStrategy.KeepLast)
                        {
                            if (i != files.Count - 1 && file.Equals(files[i + 1]))
                            {
                                selected = true;
                            }
                        }

                        rows.Add(new DisplayFile(file.md5Hash, fileInfo.FullName, fileInfo.Length, selected));
                    }
                }

                Dispatcher.Invoke(new Action(() => dataGrid.ItemsSource = rows));
                Dispatcher.Invoke(new Action(() => lblStatus.Content = "All Done!"));
                Dispatcher.Invoke(new Action(() => btnScan.Content = "Scan"));
            }
            catch (ThreadInterruptedException) { }
            catch (TaskCanceledException) { }
            catch (ThreadAbortException)
            {
                Thread.ResetAbort();
            }
        }

        private void runDelete(DeletionManager manager)
        {
            string path;
            bool filesExist = manager.doFilesExist(out path);

            if (filesExist)
            {
                runRecycle(manager, RecycleType.File);

                if (options.removeEmptyParents)
                {
                    if (manager.containsEmptyDirectories())
                    {
                        runRecycle(manager, RecycleType.Directory);
                    }
                }
            }
            else
            {
                System.Windows.MessageBox.Show("Unable to locate the file: " + path, "Unable to locate file");
            }
        }

        private void runOpenFileLocation(DeletionManager manager)
        {
            string path;
            bool filesExist = manager.doFilesExist(out path);

            if (filesExist)
            {
                manager.openFileLocations();
            }
            else
            {
                System.Windows.MessageBox.Show("Unable to locate the file: " + path, "Unable to locate file");
            }
        }

        private void runRecycle(DeletionManager manager, RecycleType recycleType)
        {
            bool preformDelete = !options.promptForDeletion;

            if (!preformDelete)
            {
                string displayName;

                switch (recycleType)
                {
                    case RecycleType.File:
                        displayName = manager.filesDisplayName;
                        break;
                    case RecycleType.Directory:
                        displayName = manager.directoriesDisplayName;
                        break;
                    default:
                        throw new Exception("Invalid RecycleType: " + recycleType.GetHashCode());
                }

                preformDelete = System.Windows.MessageBox.Show("Are you sure you want to delete " + displayName + "?", "Are you sure", MessageBoxButton.YesNoCancel) == MessageBoxResult.Yes;
            }

            if (preformDelete)
            {
                switch (recycleType)
                {
                    case RecycleType.File:
                        manager.recycleFiles();

                        if ((object)dataGrid != null)
                        {
                            dataGrid.SelectedIndex = -1;
                        }
                        break;
                    case RecycleType.Directory:
                        manager.recycleEmptyDirectories();
                        break;
                    default:
                        throw new Exception("Invalid RecycleType: " + recycleType.GetHashCode());
                }
            }

            dataGrid.Items.Refresh();
        }
    }
}
